#include "Validator.h"
#include "Saver.h"

class ValidatorWithSave : virtual public Validator
{
private:
    string fincon_save_file_path;
    string roi_save_file_path;
    cv::Mat img_save;

    // roi *generate_roi(fincon *m_fincon) const
    // {
    //     const int n = db.size();
    //     roi *m_roi = new roi[n];
    //     for (int i = 0; i < n; i++)
    //     {
    //         const int ROI_size = 212;

    //         ROIExtracter roie(m_fincon[i].coordinates);
    //         const cv::Point *const *result = roie.extract();

    //         m_roi[i].filename = m_fincon[i].filename;
    //         for (int j = 0; j < 8; j++)
    //         {
    //             m_roi[i].coordinates[j] = j % 2 ? result[0][j / 2].y : result[0][j / 2].x;
    //         }
    //     }
    //     return m_roi;
    // }

    void save_fincon(fincon *m_fincon, int n, string fincon_save_file_path) const
    {
        //TODO:
        //do nothing;because fincons are actually generated from python output
        //it will be better to call python code using c++ rather than running python outside
    }

    void save_roi(roi *m_roi, int n, const string &roi_save_file_path) const
    {
        Saver<roi> s;
        s.save(m_roi, db.size(), roi_save_file_path);
    }

    void save_fincon_roi(const string &save_name, int *fincon, int Sx[4], int Sy[4])
    {
        cv::circle(this->img_save, cv::Point2d(fincon[0], fincon[1]), 5, cv::Scalar(0, 0, 255), 2, 8, 0);
        cv::circle(this->img_save, cv::Point2d(fincon[4], fincon[5]), 5, cv::Scalar(0, 0, 255), 2, 8, 0);
        cv::Point **result = new cv::Point *[1];
        int pt_num = 4;
        result[0] = new cv::Point[pt_num];
        result[0][0] = cv::Point(Sy[0], Sx[0]);
        result[0][1] = cv::Point(Sy[1], Sx[1]);
        result[0][2] = cv::Point(Sy[2], Sx[2]);
        result[0][3] = cv::Point(Sy[3], Sx[3]);
        cv::polylines(img_save, (const cv::Point **)result, &pt_num, 1, true, cv::Scalar(255, 0, 0));
        cv::imwrite(roi_save_file_path + save_name, this->img_save);

        delete[] result[0];
        delete[] result;
    }

protected:
public:
    ValidatorWithSave(Database &db, string &fincon_save_file_path, string &roi_save_file_path) : Validator(db), fincon_save_file_path(fincon_save_file_path), roi_save_file_path(roi_save_file_path){
                                                                                                                                                                  //TODO:
                                                                                                                                                                  // fincon *m_fincon = Validator::generate_fincon();
                                                                                                                                                                  // save_fincon(m_fincon, db.size(), fincon_save_file_path);

                                                                                                                                                                  // roi *m_roi = generate_roi(m_fincon);
                                                                                                                                                                  // save_roi(m_roi, db.size(), roi_save_file_path);

                                                                                                                                                                  // delete[] m_fincon;
                                                                                                                                                                  // delete[] m_roi;
                                                                                                                                                              };
    ~ValidatorWithSave();

    virtual float validate(const palmprint &pp, int suspect_perison_id, const float TH)
    {
        int *fincon, Sx[4], Sy[4];
        pp.img.copyTo(this->img_save);

        fincon = Validator::get_fincon_coordinates(pp);
        Validator::get_roi_coordinates(pp, fincon, Sx, Sy);
        this->save_fincon_roi(pp.filename, fincon, Sx, Sy);

        delete fincon;
        return Validator::validate(pp, suspect_perison_id, TH);
    };
};

ValidatorWithSave::~ValidatorWithSave()
{
}
